`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/08/03 23:02:36
// Design Name: 
// Module Name: WeightBufferTest
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module WeightBufferTest;
parameter ADDR_WIDTH = 32;
parameter DATA_WIDTH = 32;
parameter Tn = 4;
parameter Tm = 8;
parameter K = 3;
//
logic clk;
logic rst;
logic [ADDR_WIDTH-1:0] rd_addr;
logic [DATA_WIDTH-1:0] rd_data [0:Tm-1][0:Tn-1];
logic [31:0] m;
logic [31:0] n;
logic [31:0] kk;
logic we;
logic [DATA_WIDTH-1:0] wr_data;
//
logic [DATA_WIDTH-1:0] mem [0:Tm-1][0:Tn-1][0:K*K-1];
logic start_write;
logic writing;
logic write_done;
logic start_read;
logic read_done;
//clk
initial begin
    clk=0;
    forever begin
        #5 clk=~clk;
    end
end
//rst
initial begin
    rst=1;
    #20
    rst=0;
end
//mem
initial begin
    for(int m=0;m<Tm;m++)
        for(int n=0;n<Tn;n++)
            for(int kk=0;kk<K*K;kk++)
                mem[m][n][kk]=m*Tn*K*K+n*K*K+kk;
end
//start_write
initial begin
    start_write=0;
    #100
    start_write=1;
    #10
    start_write=0;
end
//writing
always_ff@(posedge clk)
if(start_write)
    writing<=1;
else if(write_done)
    writing<=0;
//
assign we=writing;
assign wr_data=mem[m][n][kk];
//m,n,kk
always_ff@(posedge clk)
if(start_write)
begin
    m<=0;
    n<=0;
    kk<=0;
end
else if(writing)
begin
    if(kk==K*K-1)
        if(n==Tn-1)
        begin
            m<=m+1;
            n<=0;
            kk<=0;
        end
        else
        begin
            n<=n+1;
            kk<=0;
        end
    else
    begin
        kk<=kk+1;
    end
end
//write_done
assign write_done=(m==Tm-1&&n==Tn-1&&kk==K*K-1)?1:0;
//start_read
always_ff@(posedge clk,posedge rst)
if(rst)
    start_read<=0;
else if(write_done)
    start_read<=1;
else
    start_read<=0;
//rd_addr
always_ff@(posedge clk,posedge rst)
if(rst)
    rd_addr<=0;
else if(start_read)
    rd_addr<=0;
else
    rd_addr<=rd_addr+1;
/******************************************************************************/
//inst
WeightBuffer
#(.ADDR_WIDTH(32),
  .DATA_WIDTH(32),
  .Tn(4),
  .Tm(8),
  .K(3))
U(
.clk(clk),
.rst(rst),
//多端口read
.rd_addr(rd_addr),
.rd_data(rd_data),
//单端口write
.m(m),
.n(n),
.kk(kk),
.wr_data(wr_data),
.we(we)
);
endmodule
